﻿using Inaction;
using Inaction.ServiceContract;
using Inaction.Core;
using Inaction.Criteria;
using Inaction.Mapping;
using Inaction.Message;
using Inaction.Util;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;

namespace Inaction
{
    [Serializable]
    public abstract partial class Entity<T> : Model<T>, INotifyPropertyChanging, INotifyPropertyChanged
        where T : Entity<T>, new()
    {
        public Entity()
        {
            if (AppConfig.Instance.RunLocation == RunLocation.Client)
            {
                Key = GetHashCode();
            }
        }

        #region 属性
        public static Mapping.ClassInfo ClassInfo
        {
            get
            {
                return Mapping.ClassInfo.LoadInfo(typeof(T));
            }
        }

        public static readonly Property<bool> SelectedProperty = RegisteProperty<bool>(p => p.Selected);
        bool selected = false;
        [DisplayName("选择")]
        public bool Selected
        {
            get { return selected; }
            set { SetProperty(SelectedProperty, ref selected, value); }
        }
        #endregion

        #region override

        internal protected override void Init(System.Data.IDataReader reader)
        {
            for (int i = 0; i < reader.FieldCount; i++)
            {
                var value = reader.GetValue(i);
                if (value != DBNull.Value)
                {
                    var columnName = reader.GetName(i);
                    var property = ClassInfo.MappedProperties[columnName];
                    value = TypeConvert.ConvertToSystemValue(property.UnderlyingType, value);
                    property.SetFieldValue((T)this, value);
                }
            }
            MarkNone();
        }

        protected override void SetProperty<P>(Property<P> property, ref P field, P newValue)
        {
            if (newValue == null && field == null) return;
            else if (field != null && field.Equals(newValue)) return;
            if (PropertyChanging != null)
                PropertyChanging(this, new PropertyChangingEventArgs(property.Name));
            OnPropertyChanging(property);
            field = newValue;
            if (isSelfDirty == false)
            {
                isSelfDirty = true;
            }
            OnPropertyChanged(property);
            if (PropertyChanged != null)
            {
                try
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(property.Name));
                }
                catch (Exception e)
                {
                    MessageHost.ShowMessage(e.GetMessage());
                }
            }
        }

        #endregion
    }
}